package infra

import (
	"context"
	"time"

	"github.com/google/wire"
	"github.com/pkg/errors"
	"github.com/redis/go-redis/v9"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

var ClientSet = wire.NewSet(InitMySQLDB, GormTransClientSet, InitRedis)

func InitMySQLDB() (*gorm.DB, error) {
	dsn := "root:root@tcp(127.0.0.1:3306)/study?charset=utf8mb4&parseTime=True&loc=Local"
	return gorm.Open(mysql.Open(dsn), &gorm.Config{})
}

var GormTransClientSet = wire.NewSet(wire.Struct(new(GormTransClient), "*"))

type GormTransClient struct {
	DB *gorm.DB
}

func (a *GormTransClient) Exec(ctx context.Context, fn func(context.Context) error) error {
	if _, ok := FromTrans(ctx); ok {
		return fn(ctx)
	}

	return a.DB.Transaction(func(db *gorm.DB) error {
		return fn(NewTrans(ctx, db))
	})
}

func InitRedis() (*redis.Client, error) {
	redisClient := redis.NewClient(&redis.Options{
		Addr:         "localhost:6379",
		Password:     "rdnredis",
		DB:           0,
		MinIdleConns: 50,              // 保持最小空闲连接
		PoolTimeout:  1 * time.Second, // 等待连接超时
		ReadTimeout:  3 * time.Second, // 读操作超时
		WriteTimeout: 3 * time.Second, // 写操作超时

		// 连接健康检查
		ConnMaxIdleTime: 5 * time.Minute, // 空闲连接自动关闭
		ConnMaxLifetime: 1 * time.Hour,   // 连接最大存活时间
	})
	if err := redisClient.Ping(context.Background()).Err(); err != nil {
		panic(errors.WithStack(err))
	}
	return redisClient, nil
}
